
#ifndef Effect_h
#define Effect_h

#include <System/Object.h>
#include <System/Collections/Generic/List.h>
#include <System/Collections/Generic/Dictionary.h>
#include <System/Array.h>
#include <System/ArgumentNullException.h>

#include "../GraphicsResource.h"
#include "../Shader/Shader.h"
#include "../Shader/ConstantBuffer.h"

#include "EffectParameterClass.h"
#include "EffectParameterType.h"
#include "../States/StencilOperation.h"
#include "../States/BlendFunction.h"
#include "../States/CompareFunction.h"
#include "../States/Blend.h"

namespace Riccsson
{
	namespace Xna
	{
		namespace Framework
		{
			namespace Graphics
			{
				class EffectParameterCollection;
				class EffectTechniqueCollection;
				class EffectPassCollection;
				class EffectTechnique;
				class Shader;
				class ConstantBuffer;
				class GraphicsDevice;
				class BinaryReader;

				class Effect
					: public GraphicsResource
				{
					public: GC_PTR<EffectParameterCollection> Parameters; // { get; private: set; }

					public: GC_PTR<EffectTechniqueCollection> Techniques; // { get; private: set; }

					public: GC_PTR<EffectTechnique> CurrentTechnique;
  
					public: /*internal*/ GC_PTR<Riccsson::System::Array<GC_PTR<ConstantBuffer>>> ConstantBuffers; // { get; private: set; }

					private: GC_PTR<Riccsson::System::Collections::Generic::List<GC_PTR<Shader>>> _shaderList;

					private: /*readonly*/ bool _isClone;
							 
					/// <summary>
					/// The MonoGame Effect file format header identifier.
					/// </summary>
					private: const GC_PTR<Riccsson::System::string> MGFXHeader;

					/// <summary>
					/// The current MonoGame Effect file format versions
					/// used to detect old packaged content.
					/// </summary>
					/// <remarks>
					/// We should avoid supporting old versions for very long as
					/// users should be rebuilding content when packaging their game.
					/// </remarks>
					private: const int MGFXVersion;

					public: /*internal*/ Effect(GC_PTR<GraphicsDevice> graphicsDevice)
						: MGFXHeader( new Riccsson::System::String("MGFX") )
						, MGFXVersion( 4 )
					{
						throw;
					}
			
					protected: Effect(GC_PTR<Effect> cloneSource)
					//	: this(cloneSource.GraphicsDevice)
						: MGFXHeader( new Riccsson::System::String("MGFX") )
						, MGFXVersion( 4 )
					{
						throw;
					}

					public: Effect (GC_PTR<GraphicsDevice> graphicsDevice, Riccsson::System::Array<byte>* effectCode)
					//	: this(graphicsDevice)
						: MGFXHeader( new Riccsson::System::String("MGFX") )
						, MGFXVersion( 4 )
					{
						throw;
					}

					/// <summary>
					/// Clone the source into this existing object.
					/// </summary>
					/// <remarks>
					/// Note this is not overloaded in derived classes on purpose.  This is
					/// only a reason this exists is for caching effects.
					/// </remarks>
					/// <param name="cloneSource">The source effect to clone from.</param>
					private: void Clone(Effect cloneSource)
					{
						throw;
					}

					/// <summary>
					/// Returns a deep copy of the effect where immutable types 
					/// are shared and mutable data is duplicated.
					/// </summary>
					/// <remarks>
					/// See "Cloning an Effect" in MSDN:
					/// http://msdn.microsoft.com/en-us/library/windows/desktop/ff476138(v=vs.85).aspx
					/// </remarks>
					/// <returns>The cloned effect.</returns>
					public: virtual GC_PTR<Effect> Clone()
					{
						throw;
					}

					public: void End()
					{
					}

					protected: public: /*internal*/ virtual bool OnApply()
					{
						return false;
					}

					protected: override void Dispose(bool disposing)
					{
						throw;
					}

					public: /*internal*/ protected: override void GraphicsDeviceResetting()
					{
						throw;
					}

					#pragma region Effect File Reader

					public: /*internal*/ static Riccsson::System::Array<byte>* LoadEffectResource(Riccsson::System::string* name)
					{
						throw;
					}

			#if !PSM

					private: void ReadEffect (BinaryReader* reader)
					{
						throw;
					}

					private: static GC_PTR<EffectAnnotationCollection> ReadAnnotations(BinaryReader* reader)
					{
						throw;
					}

					private: static GC_PTR<EffectPassCollection> ReadPasses(BinaryReader* reader, Effect* effect, Riccsson::System::Collections::Generic::List<Shader>* shaders)
					{
						throw;
					}

					private: static GC_PTR<EffectParameterCollection> ReadParameters(BinaryReader* reader)
					{
						throw;
					}
			#else //PSM
					public: /*internal*/ void ReadEffect(BinaryReader reader)
					{
						throw;
					}
        
					public: /*internal*/ EffectParameter EffectParameterForUniform(ShaderProgram shaderProgram, int index)
					{
						throw;
					}
        
			#endif
					#pragma endregion // Effect File Reader


					#pragma region Effect Cache        

					/// <summary>
					/// The cache of effects from unique byte streams.
					/// </summary>
					private: static readonly Riccsson::System::Collections::Generic::Dictionary<int, GC_PTR<Effect>> EffectCache;

					public: /*internal*/ static void FlushCache()
					{
						throw;
					}

					#pragma endregion // Effect Cache

				};
			}
		}
	}
}

#endif